package com.gmp.rooms.controller;

import java.util.*;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gmp.common.utils.StringUtils;
import com.gmp.common.utils.bean.BeanUtils;
import com.gmp.rooms.domain.Facilities;
import com.gmp.rooms.domain.Rooms;
import com.gmp.rooms.domain.vo.EquipmentInspectionQueryVo;
import com.gmp.rooms.service.IFacilitiesService;
import com.gmp.rooms.service.IRoomsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.gmp.common.annotation.Log;
import com.gmp.common.core.controller.BaseController;
import com.gmp.common.core.domain.AjaxResult;
import com.gmp.common.enums.BusinessType;
import com.gmp.rooms.domain.EquipmentInspection;
import com.gmp.rooms.service.IEquipmentInspectionService;
import com.gmp.common.utils.poi.ExcelUtil;
import com.gmp.common.core.page.TableDataInfo;

/**
 * 设备巡检记录Controller
 *
 * @author Koi
 * @date 2025-08-02
 */
@RestController
@RequestMapping("/rooms/EquipmentInspection")
@Api(tags = "设备巡检记录管理")
public class EquipmentInspectionController extends BaseController {
    @Autowired
    private IEquipmentInspectionService equipmentInspectionService;

    @Autowired
    private IRoomsService roomsService;

    @Autowired
    private IFacilitiesService facilitiesService;

    /**
     * 查询设备巡检记录列表
     */
    @PreAuthorize("@ss.hasPermi('rooms:EquipmentInspection:list')")
    @GetMapping("/list")
    @ApiOperation("设备巡检记录列表（厂房→设备树形结构）")
    public TableDataInfo list(EquipmentInspection equipmentInspection) {
        // 1. 查询所有设备巡检记录（原逻辑不变）
        LambdaQueryWrapper<EquipmentInspection> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(equipmentInspection.getRoomCode())) {
            queryWrapper.eq(EquipmentInspection::getRoomCode, equipmentInspection.getRoomCode());
        }
        if (StringUtils.isNotBlank(equipmentInspection.getFacilityCode())) {
            queryWrapper.eq(EquipmentInspection::getFacilityCode, equipmentInspection.getFacilityCode());
        }
        List<EquipmentInspection> inspectionList = equipmentInspectionService.list(queryWrapper);


        // 2. 转换为 VO 并关联名称（厂房名称、设备名称）（优化关联查询效率）
        List<EquipmentInspectionQueryVo> voList = new ArrayList<>();
        for (EquipmentInspection inspection : inspectionList) {
            EquipmentInspectionQueryVo vo = new EquipmentInspectionQueryVo();
            BeanUtils.copyBeanProp(vo, inspection);

            // 关联厂房名称（按roomCode唯一查询，避免list冗余）
            if (StringUtils.isNotBlank(inspection.getRoomCode())) {
                Rooms room = roomsService.getOne(
                        new LambdaQueryWrapper<Rooms>().eq(Rooms::getRoomCode, inspection.getRoomCode())
                );
                if (room != null) {
                    vo.setRoomName(room.getRoomName());
                }
            }

            // 关联设备名称（按facilityCode唯一查询，确保设备信息准确）
            if (StringUtils.isNotBlank(inspection.getFacilityCode())) {
                Facilities facility = facilitiesService.getOne(
                        new LambdaQueryWrapper<Facilities>().eq(Facilities::getFacilityCode, inspection.getFacilityCode())
                );
                if (facility != null) {
                    vo.setFacilityName(facility.getFacilityName());
                }
            }

            voList.add(vo);
        }


        // 3. 关键修正：按设备编码（facilityCode）分组，只保留最新巡检记录
        List<EquipmentInspectionQueryVo> uniqueVoList = new ArrayList<>();
        // 3.1 按facilityCode分组（key：设备唯一编码，value：该设备的所有巡检记录）
        Map<String, List<EquipmentInspectionQueryVo>> facilityGroup = voList.stream()
                // 过滤设备编码为空的无效记录（避免空key分组）
                .filter(vo -> StringUtils.isNotBlank(vo.getFacilityCode()))
                .collect(Collectors.groupingBy(EquipmentInspectionQueryVo::getFacilityCode));

        // 3.2 每组内按“巡检时间”倒序排序，取最新一条记录（若巡检时间相同，按创建时间倒序）
        for (Map.Entry<String, List<EquipmentInspectionQueryVo>> entry : facilityGroup.entrySet()) {
            List<EquipmentInspectionQueryVo> sameFacilityVos = entry.getValue();
            // 排序规则：先按inspectionTime倒序（最新巡检优先），再按createdAt倒序（同时间取最新创建）
            EquipmentInspectionQueryVo latestVo = sameFacilityVos.stream()
                    .sorted((vo1, vo2) -> {
                        // 1. 先比较巡检时间（inspectionTime：String类型，ISO格式如"2025-09-18"）
                        int timeCompare = vo2.getInspectionTime().compareTo(vo1.getInspectionTime());
                        if (timeCompare != 0) {
                            return timeCompare; // 巡检时间不同，直接按巡检时间排序
                        }
                        // 2. 巡检时间相同，按创建时间（createdAt）倒序（确保取最新录入的记录）
                        return vo2.getCreatedAt().compareTo(vo1.getCreatedAt());
                    })
                    .findFirst() // 取排序后的第一条（最新记录）
                    .orElse(null);

            if (latestVo != null) {
                uniqueVoList.add(latestVo);
            }
        }


        // 4. 基于去重后的VO列表，构建“厂房→设备”树形结构
        // 4.1 按厂房编码（roomCode）分组（同一厂房的设备归为一组）
        Map<String, List<EquipmentInspectionQueryVo>> roomGroup = uniqueVoList.stream()
                .filter(vo -> StringUtils.isNotBlank(vo.getRoomCode()))
                .collect(Collectors.groupingBy(EquipmentInspectionQueryVo::getRoomCode));

        // 4.2 组装树形结构（厂房为父节点，设备为子节点）
        List<EquipmentInspectionQueryVo> treeList = new ArrayList<>();
        for (Map.Entry<String, List<EquipmentInspectionQueryVo>> entry : roomGroup.entrySet()) {
            String roomCode = entry.getKey();
            List<EquipmentInspectionQueryVo> deviceVos = entry.getValue();

            // 构建厂房父节点（复用该厂房第一条设备的名称，确保厂房信息准确）
            EquipmentInspectionQueryVo roomVo = new EquipmentInspectionQueryVo();
            roomVo.setRoomCode(roomCode);
            roomVo.setRoomName(deviceVos.get(0).getRoomName()); // 同一厂房的设备roomName一致
            roomVo.setType("厂房"); // 标记节点类型为“厂房”
            roomVo.setChildren(new ArrayList<>()); // 初始化子节点列表（存储设备）

            // 构建设备子节点（标记类型为“设备”，清除子节点字段避免冗余）
            List<EquipmentInspectionQueryVo> childDevices = deviceVos.stream()
                    .peek(device -> {
                        device.setType("设备"); // 标记节点类型为“设备”
                        device.setChildren(null); // 设备是叶子节点，子节点设为null
                    })
                    .collect(Collectors.toList());

            // 关联设备子节点到厂房父节点
            roomVo.getChildren().addAll(childDevices);
            treeList.add(roomVo);
        }


        // 5. 构造返回结果（总记录数为去重后的设备数，与树形结构一致）
        TableDataInfo dataInfo = new TableDataInfo();
        dataInfo.setTotal(uniqueVoList.size()); // 总记录数=去重后的设备数量（非原始巡检记录数）
        dataInfo.setRows(treeList); // 树形结构数据（厂房→设备，无重复设备）
        dataInfo.setCode(200);
        dataInfo.setMsg("查询成功");
        return dataInfo;
    }


    /**
     * 导出设备巡检记录列表
     */
    @PreAuthorize("@ss.hasPermi('rooms:EquipmentInspection:export')")
    @Log(title = "设备巡检记录", businessType = BusinessType.EXPORT)
    @ApiOperation("导出设备巡检记录列表")
    @PostMapping("/export")
    public void export(HttpServletResponse response, EquipmentInspection equipmentInspection) {
        List<EquipmentInspection> list = equipmentInspectionService.selectEquipmentInspectionList(equipmentInspection);
        ExcelUtil<EquipmentInspection> util = new ExcelUtil<EquipmentInspection>(EquipmentInspection.class);
        util.exportExcel(response, list, "设备巡检记录数据");
    }

    /**
     * 获取设备巡检记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('rooms:EquipmentInspection:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") String id) {
        return success(equipmentInspectionService.selectEquipmentInspectionById(id));
    }

    /**
     * 新增设备巡检记录
     */
    @PreAuthorize("@ss.hasPermi('rooms:EquipmentInspection:add')")
    @Log(title = "设备巡检记录", businessType = BusinessType.INSERT)
    @ApiOperation("新增设备巡检记录")
    @PostMapping
    public AjaxResult add(@RequestBody EquipmentInspection equipmentInspection) {
        String RoomsCode = equipmentInspection.getRoomCode();
        LambdaQueryWrapper<Rooms> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Rooms::getRoomCode, RoomsCode);
        Rooms rooms = roomsService.getOne(queryWrapper);
        String equipmentStatus = equipmentInspection.getStatus();
        if(equipmentStatus.equals("正常")){
            rooms.setStateEvaluation("设备正常");
            roomsService.saveOrUpdate(rooms);
        }
        else{
            rooms.setStateEvaluation("有设备异常");
            roomsService.saveOrUpdate(rooms);
        }
        return toAjax(equipmentInspectionService.insertEquipmentInspection(equipmentInspection));
    }

    /**
     * 修改设备巡检记录
     */
    @PreAuthorize("@ss.hasPermi('rooms:EquipmentInspection:edit')")
    @Log(title = "设备巡检记录", businessType = BusinessType.UPDATE)
    @ApiOperation("修改设备巡检记录")
    @PutMapping
    public AjaxResult edit(@RequestBody EquipmentInspection equipmentInspection) {
        // 1. 构建查询条件（根据设备编码更新）
        LambdaQueryWrapper<EquipmentInspection> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EquipmentInspection::getFacilityCode, equipmentInspection.getFacilityCode());

        // 2. 执行更新操作（注意：第一个参数是要更新的实体对象，第二个是查询条件）
        // 确保equipmentInspection中包含了需要更新的字段值（如巡检时间、状态等）
        boolean updateResult = equipmentInspectionService.update(equipmentInspection, queryWrapper);

        // 3. 根据更新结果返回对应信息
        if (updateResult) {
            return AjaxResult.success("设备巡检记录更新成功");
        } else {
            return AjaxResult.error("设备巡检记录更新失败，未找到对应设备或无需更新");
        }
    }

    /**
     * 删除设备巡检记录
     */
    @PreAuthorize("@ss.hasPermi('rooms:EquipmentInspection:remove')")
    @Log(title = "设备巡检记录", businessType = BusinessType.DELETE)
    @ApiOperation("删除设备巡检记录")
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable String[] ids) {
        return toAjax(equipmentInspectionService.removeBatchByIds(Arrays.asList(ids)));
    }


    /**
     * 查询设备巡检记录列表
     */
    @PreAuthorize("@ss.hasPermi('rooms:DeviceRecord:list')")
    @GetMapping("/listRecord")
    @ApiOperation("查看巡检设备列表")
    public TableDataInfo listRecord(EquipmentInspection equipmentInspection) {


        // 2. 构建巡检记录的查询条件（筛选条件与之前一致）
        LambdaQueryWrapper<EquipmentInspection> queryWrapper = new LambdaQueryWrapper<>();
        // 设备ID筛选
        queryWrapper.eq(equipmentInspection.getFacilityCode() != null,
                EquipmentInspection::getFacilityCode, equipmentInspection.getFacilityCode());
        // 厂房编号筛选（通过roomCode筛选，与Rooms表的roomCode对应）
        queryWrapper.eq(equipmentInspection.getRoomCode() != null,
                EquipmentInspection::getRoomCode, equipmentInspection.getRoomCode());
        // 巡检时间筛选
        queryWrapper.eq(equipmentInspection.getInspectionTime() != null,
                EquipmentInspection::getInspectionTime, equipmentInspection.getInspectionTime());
        // 创建时间筛选
        queryWrapper.eq(equipmentInspection.getCreatedAt() != null,
                EquipmentInspection::getCreatedAt, equipmentInspection.getCreatedAt());
        // 按巡检时间降序（最新记录在前）
        queryWrapper.orderByDesc(EquipmentInspection::getInspectionTime);
        // 2. 查询原始巡检记录
        List<EquipmentInspection> inspectionList = equipmentInspectionService.list(queryWrapper);

        // 3. 提取关联的roomCode和facilityCode（用于批量查询）
        final Set<String> roomCodes = inspectionList.stream()
                .filter(inspection -> inspection.getRoomCode() != null)
                .map(EquipmentInspection::getRoomCode)
                .collect(Collectors.toSet());

        final Set<String> facilityCodes = inspectionList.stream()
                .filter(inspection -> inspection.getFacilityCode() != null)
                .map(EquipmentInspection::getFacilityCode)
                .collect(Collectors.toSet());

        // 4. 批量查询厂房名称
        final Map<String, String> roomNameMap = new HashMap<>();
        if (!roomCodes.isEmpty()) {
            LambdaQueryWrapper<Rooms> roomWrapper = new LambdaQueryWrapper<>();
            roomWrapper.in(Rooms::getRoomCode, roomCodes);
            List<Rooms> roomsList = roomsService.list(roomWrapper);
            roomNameMap.putAll(roomsList.stream()
                    .collect(Collectors.toMap(Rooms::getRoomCode, Rooms::getRoomName, (k1, k2) -> k1)));
        }

        // 5. 批量查询设备名称
        final Map<String, String> facilityNameMap = new HashMap<>();
        if (!facilityCodes.isEmpty()) {
            LambdaQueryWrapper<Facilities> facilityWrapper = new LambdaQueryWrapper<>();
            facilityWrapper.in(Facilities::getFacilityCode, facilityCodes);
            List<Facilities> facilitiesList = facilitiesService.list(facilityWrapper);
            facilityNameMap.putAll(facilitiesList.stream()
                    .collect(Collectors.toMap(Facilities::getFacilityCode, Facilities::getFacilityName, (k1, k2) -> k1)));
        }

        // 6. 转换为VO并设置扩展字段
        List<EquipmentInspectionQueryVo> queryVoList = inspectionList.stream()
                .map(inspection -> {
                    EquipmentInspectionQueryVo vo = new EquipmentInspectionQueryVo();
                    BeanUtils.copyProperties(inspection, vo);
                    vo.setRoomName(roomNameMap.getOrDefault(inspection.getRoomCode(), "未知厂房"));
                    vo.setFacilityName(facilityNameMap.getOrDefault(inspection.getFacilityCode(), "未知设备"));
                    return vo;
                })
                .collect(Collectors.toList());


        // 7. 返回分页结果（若需分页，需在查询前开启分页插件）
        return getDataTable(queryVoList);
    }


}
